package com.skivingcloud.admin.annotation;

import com.skivingcloud.admin.feignclient.FSysLogService;
import com.skivingcloud.admin.sys.entity.User;
import com.skivingcloud.admin.sys.model.SysLog;
import com.skivingcloud.common.utils.UuidUtil;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.web.subject.WebSubject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

/**
 * 记录系统用户操作日期切面定义
 * 
 * @author Lanvo
 *
 */
@Aspect
@Component
public class OperateLogAspect {
	// 本地异常日志记录对象
	// private static final Logger logger =
	// LoggerFactory.getLogger(OperateLogAspect. class);

	// Controller层切点
	@Pointcut("@annotation(com.skivingcloud.admin.annotation.UserOperateLog)")
	public void controllerAspect() {
	}

	/*
	 * @Autowired private SysLogService fSysLogServices;
	 */
	@Autowired
	private FSysLogService fSysLogServices;

	/**
	 * 操作异常记录
	 * 
	 * @descript
	 * @param point
	 * @param e
	 */
	@AfterThrowing(pointcut = "controllerAspect()", throwing = "e")
	public void doAfterThrowing(JoinPoint point, Throwable e) {
		String ip = null;
		String description = e.toString();
		UserOperateLog userOperateLog = null;
		User user = null;
		String clientType = null;
		String mobileUuid = null;

		try {
			HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils.getSubject())
					.getServletRequest();
			Device currentDevice = DeviceUtils.getCurrentDevice(request);
			if (currentDevice.isMobile() || currentDevice.isTablet()) {
				// 移动端：手机或平板设备需要从请求头中获取设备编号存起来
				clientType = currentDevice.isMobile() ? "2" : "3";
				mobileUuid = request.getHeader("annuityMobileUuid");
			} else {
				clientType = "1";
			}
			ip = request.getHeader("x-forwarded-for");
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("WL-Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_CLIENT_IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_X_FORWARDED_FOR");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
			}
			// ip = SecurityUtils.getSubject().getSession().getHost();
		} catch (Exception ee) {
			description = ",无法获取登录用户Ip";
		}
		try {

			Signature signature = point.getSignature();
			MethodSignature methodSignature = (MethodSignature) signature;
			Method targetMethod = methodSignature.getMethod();

			userOperateLog = (UserOperateLog) targetMethod.getAnnotation(UserOperateLog.class);

			// 登录名
			user = (User) SecurityUtils.getSubject().getSession().getAttribute("userSession");
			if (user == null) {
				description = description + ",无法获取登录用户信息！";
			}
		} catch (Exception ee) {
			description = description + ",无法获取登录用户信息！";
		}
		// 使用spring EL表达式获取参数中的值
		// String bussid = (String) AspectSupportUtils.getKeyValue(point,
		// userOperateLog.bussid());
		// System.out.println("---------业务id：" + bussid);
		SysLog sysLog = new SysLog();
		if (user != null)
			sysLog.setUserId(user.getId());

		sysLog.setModule(userOperateLog.module());
		sysLog.setMethods(userOperateLog.methods());
		sysLog.setDescription(e.toString());
		sysLog.setActionTime("0");
		sysLog.setUserIp(ip);
		sysLog.setOperTime(new Date());
		sysLog.setId(UuidUtil.get32UUID());

		sysLog.setBussid(userOperateLog.bussid());// 业务id
		sysLog.setClientType(clientType);// 终端类型1-PC端、2-手机、3-平板、4-其他设备
		sysLog.setMobileUuid(mobileUuid);// 移动端唯一标识
		sysLog.setFunctionNo(userOperateLog.functionNo());// 功能编号

		try {
			// fSysLogServices.insertLog(sysLog);
			fSysLogServices.save(sysLog);
		} catch (Exception eee) {
			eee.printStackTrace();
		}

	}

	/**
	 * 后置通知 用于拦截Controller层记录用户的操作
	 *
	 * @param point 切点
	 */
	@Around("controllerAspect()")
	public Object doController(ProceedingJoinPoint point) {
		Object result = null;
		String description = null;
		Long start = 0L;
		Long end = 0L;
		Long time = 0L;
		String ip = null;
		UserOperateLog userOperateLog = null;
		String clientType = null;
		String mobileUuid = null;

		// 当前用户
		try {
			Signature signature = point.getSignature();
			MethodSignature methodSignature = (MethodSignature) signature;
			Method targetMethod = methodSignature.getMethod();
			userOperateLog = (UserOperateLog) targetMethod.getAnnotation(UserOperateLog.class);

			// 执行方法所消耗的时间
			start = System.currentTimeMillis();
			result = point.proceed();
			end = System.currentTimeMillis();
			time = end - start;
		} catch (Throwable e) {
			throw new RuntimeException(e);
		}
		description = userOperateLog.description();
		try {
			HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils.getSubject())
					.getServletRequest();
			Device currentDevice = DeviceUtils.getCurrentDevice(request);
			if (currentDevice.isMobile() || currentDevice.isTablet()) {
				// 移动端：手机或平板设备需要从请求头中获取设备编号存起来
				clientType = currentDevice.isMobile() ? "2" : "3";
				mobileUuid = request.getHeader("annuityMobileUuid");
			} else {
				clientType = "1";
			}
			ip = request.getHeader("x-forwarded-for");
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("WL-Proxy-Client-IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_CLIENT_IP");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_X_FORWARDED_FOR");
			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
			}
			// ip = SecurityUtils.getSubject().getSession().getHost();
		} catch (Exception e) {
			description = description + ",无法获取登录用户Ip";
		}
		User user = null;
		try {
			// 登录名
			user = (User) SecurityUtils.getSubject().getSession().getAttribute("userSession");
			if (user == null) {
				description = description + ",无法获取登录用户信息！";
			}
		} catch (Exception e) {
			description = description + ",无法获取登录用户信息！";
		}

		// 使用spring EL表达式获取参数中的值
		Object des = AnnotationResolver.newInstance().resolver(point, userOperateLog.description());
		Object bussid = AnnotationResolver.newInstance().resolver(point, userOperateLog.bussid());
		SysLog sysLog = new SysLog();

		if (user != null)
			sysLog.setUserId(user.getId());

		sysLog.setModule(userOperateLog.module());
		sysLog.setMethods(userOperateLog.methods());
		sysLog.setDescription(des != null ? des.toString() : description);
		sysLog.setActionTime(time.toString());
		sysLog.setUserIp(ip);
		sysLog.setOperTime(new Date());
		sysLog.setId(UuidUtil.get32UUID());

		sysLog.setBussid(bussid != null ? bussid.toString() : userOperateLog.bussid());// 业务id
		sysLog.setClientType(clientType);// 终端类型1-PC端、2-手机、3-平板、4-其他设备
		sysLog.setMobileUuid(mobileUuid);// 移动端唯一标识
		sysLog.setFunctionNo(userOperateLog.functionNo());// 功能编号

		try {
			// fSysLogServices.insertLog(sysLog);
			fSysLogServices.save(sysLog);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

}